package client;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JLabel;
import java.awt.GridLayout;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.JButton;
import javax.swing.JSeparator;
import javax.swing.border.SoftBevelBorder;
import javax.swing.border.BevelBorder;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import spel.*;
import javax.swing.JMenuItem;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JPopupMenu;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JTextField;
import java.awt.GridBagLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JComboBox;

import ai.MensStrategie;
import ai.PuntenStrategie;

import javax.swing.JCheckBox;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
/**
 * Een GUI voor de Client voor een spelletje PentagoXL
 * Is in staat een singleplayergame te spelen of te verbinden met een server om daar te spelen
 * @author Tim
 *
 */
public class ClientGUI extends JFrame implements Observer {

	private JPanel contentPane;
	private JSpinner spinner_playernumber;
	private JPanel panel_Field;
	private JPanel panel_Drawn;
	private JTextField txtLocalhost;
	private JTextField textField_Port;
	private JTextField textField_User;
	private JButton button_multi;
	private JSpinner spinner_multiplayers;

	private Client client;
	private JTextArea textArea_msg;
	private JTextField textField_chat;
	private HashMap<String, ai.Strategie> ais;
	private JSpinner spinner_timeout;
	private JComboBox<String> comboBox_AI;
	private JCheckBox chckbxEnableAi;
	private String[] hintNaam = new String[] {
			"Willie wijsneus vindt dit een goede zet:",
			"Volgens de sterren is dit gunstig:",
			"Volgens Henk is dit de beste zet:",
			"Calculating.....................:",
			"huh, ow, uhm, doe dit maar:",
			"Pietertje denk dat dit misschien wel\neen beetje goed zou kunnen zijn:",
			"Duuuuuuuude, probeer dit eens:" };

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					ClientGUI frame = new ClientGUI();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public ClientGUI() {
		ais = new HashMap<String, ai.Strategie>();
		ais.put("Next Empty", new ai.NextLeegStrategie());
		ais.put("Punten", new ai.PuntenStrategie());
		ais.put("Punten en draai", new ai.PuntenStrategieMetDraai());
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent arg0) {
				if (client != null)
					client.shutdown();
				ClientGUI.this.dispose();
			}
		});
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 846, 581);

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu mnGame = new JMenu("Single player");
		menuBar.add(mnGame);

		JPanel panel = new JPanel();
		mnGame.add(panel);
		panel.setBorder(new SoftBevelBorder(BevelBorder.RAISED, null, null,
				null, null));
		panel.setLayout(new BorderLayout(0, 0));

		JPanel panel_2 = new JPanel();
		panel.add(panel_2, BorderLayout.CENTER);
		panel_2.setLayout(new GridLayout(1, 2, 0, 0));

		JLabel lblAantalSpelers = new JLabel("Aantal spelers:");
		panel_2.add(lblAantalSpelers);

		spinner_playernumber = new JSpinner();
		spinner_playernumber.setModel(new SpinnerNumberModel(2, 2, 4, 1));
		panel_2.add(spinner_playernumber);

		JPanel panel_3 = new JPanel();
		panel.add(panel_3, BorderLayout.SOUTH);

		JButton btn_start = new JButton("Start");
		btn_start.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				startSpel();
			}
		});
		panel_3.add(btn_start);

		JLabel lblStartEenNieuw = new JLabel("Start een nieuw spel:");
		panel.add(lblStartEenNieuw, BorderLayout.NORTH);

		JMenu mnConnection = new JMenu("Connection");
		menuBar.add(mnConnection);

		JPanel panel_1 = new JPanel();
		mnConnection.add(panel_1);
		panel_1.setLayout(new GridLayout(3, 0, 0, 0));

		JPanel panel_4 = new JPanel();
		panel_1.add(panel_4);

		JLabel lblHost = new JLabel("Host:");
		panel_4.add(lblHost);

		txtLocalhost = new JTextField();
		txtLocalhost.setText("localhost");
		panel_4.add(txtLocalhost);
		txtLocalhost.setColumns(10);

		JPanel panel_5 = new JPanel();
		panel_1.add(panel_5);

		JLabel lblPort = new JLabel("Port:");
		panel_5.add(lblPort);

		textField_Port = new JTextField();
		textField_Port.setText("8080");
		textField_Port.setColumns(10);
		panel_5.add(textField_Port);

		JPanel panel_6 = new JPanel();
		panel_1.add(panel_6);

		JLabel lblUser = new JLabel("User:");
		panel_6.add(lblUser);

		textField_User = new JTextField();
		textField_User.setColumns(10);
		panel_6.add(textField_User);

		JMenuItem mntmConnect = new JMenuItem("Connect");
		mntmConnect.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				connectToServer();
			}
		});
		mnConnection.add(mntmConnect);

		JMenu mnMultiplayer = new JMenu("Multiplayer");
		menuBar.add(mnMultiplayer);

		JPanel panel_7 = new JPanel();
		panel_7.setBorder(new SoftBevelBorder(BevelBorder.RAISED, null, null,
				null, null));
		mnMultiplayer.add(panel_7);
		panel_7.setLayout(new BorderLayout(0, 0));

		JLabel lblRequestEenSpel = new JLabel("Request een spel van de server");
		panel_7.add(lblRequestEenSpel, BorderLayout.NORTH);

		JPanel panel_9 = new JPanel();
		panel_7.add(panel_9, BorderLayout.SOUTH);

		button_multi = new JButton("Start");
		button_multi.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				requestGame();
			}
		});
		panel_9.add(button_multi);

		JPanel panel_8 = new JPanel();
		panel_7.add(panel_8);
		panel_8.setLayout(new GridLayout(1, 2, 0, 0));

		JLabel label_1 = new JLabel("Aantal spelers:");
		panel_8.add(label_1);

		spinner_multiplayers = new JSpinner();
		spinner_multiplayers.setModel(new SpinnerNumberModel(2, 2, 4, 1));
		panel_8.add(spinner_multiplayers);

		JMenu mnAi = new JMenu("AI");
		menuBar.add(mnAi);

		comboBox_AI = new JComboBox<String>();
		comboBox_AI.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (comboBox_AI.getSelectedIndex() >= 0
						&& comboBox_AI.getSelectedItem() != null) {
					if (client != null)
						client.setStrategie(ais.get(comboBox_AI
								.getSelectedItem()));
				}
			}
		});

		chckbxEnableAi = new JCheckBox("Enable AI");
		chckbxEnableAi.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent arg0) {
				if (!chckbxEnableAi.isSelected()) {
					comboBox_AI.setEnabled(false);
					if (client != null)
						client.setStrategie(new MensStrategie(ClientGUI.this));
				} else {
					comboBox_AI.setEnabled(true);
					if (client != null) {
						client.setStrategie(ais.get(comboBox_AI
								.getSelectedItem()));
					}
				}
			}
		});

		JButton btnHint = new JButton("Hint?!");
		btnHint.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (client != null) {
					Zet tempzet = new PuntenStrategie().getMove(
							client.getBord(), client.getCurrentKnikker());
					addMessage(hintNaam[(int) (hintNaam.length * Math.random())]);
					addMessage("Knikker op: " + tempzet.x + ", " + tempzet.y);
					if (tempzet.richting == Zet.Richting.Links) {
						addMessage("en bord " + tempzet.index
								+ " linksom draaien.");
					} else {

						addMessage("en bord " + tempzet.index
								+ " rechtsom draaien.");

					}
				}
			}
		});
		mnAi.add(btnHint);

		JSeparator separator = new JSeparator();
		mnAi.add(separator);
		chckbxEnableAi.setSelected(true);
		mnAi.add(chckbxEnableAi);
		mnAi.add(comboBox_AI);

		for (String s : ais.keySet()) {
			comboBox_AI.addItem(s);
		}
		JLabel lblTimeout = new JLabel("timeout:");
		mnAi.add(lblTimeout);

		spinner_timeout = new JSpinner();
		spinner_timeout.setModel(new SpinnerNumberModel(new Integer(10),
				new Integer(0), null, new Integer(1)));
		mnAi.add(spinner_timeout);

		JButton btnSet = new JButton("Set");
		btnSet.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (ai.Strategie s : ais.values()) {
					s.setTimeout((int) spinner_timeout.getValue());
				}
			}
		});
		mnAi.add(btnSet);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout(0, 0));

		JPanel panel_chat = new JPanel();
		contentPane.add(panel_chat, BorderLayout.WEST);
		panel_chat.setLayout(new BorderLayout(0, 0));

		JScrollPane scrollPane = new JScrollPane();
		panel_chat.add(scrollPane, BorderLayout.CENTER);

		textArea_msg = new JTextArea();
		textArea_msg.setEditable(false);
		textArea_msg.setRows(20);
		textArea_msg.setColumns(30);
		scrollPane.setViewportView(textArea_msg);

		textField_chat = new JTextField();
		textField_chat.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				sendChatMessage();
			}
		});
		panel_chat.add(textField_chat, BorderLayout.SOUTH);
		textField_chat.setColumns(10);

		panel_Field = new JPanel();
		panel_Field.setBorder(new SoftBevelBorder(BevelBorder.RAISED, null,
				null, null, null));
		contentPane.add(panel_Field, BorderLayout.CENTER);
		panel_Field.setLayout(new BorderLayout(0, 0));

		panel_Drawn = new BordPanel();
		panel_Field.add(panel_Drawn, BorderLayout.CENTER);
		/*
		 * 
		 * 
		 * 
		 * Bord b = new Bord(); for(int i = 0; i<Bord.DIM;i++){ for(int j = 0;
		 * j<Bord.DIM;j++){ b.PlaatsKnikker(i, j, new Knikker(new
		 * Color(i*4+11*j,20*i+2*j,200-j*15),20,null)); } }
		 * ((BordPanel)panel_Drawn).updateBord(b);
		 */
	}

	private void startSpel() {
		List<Speler> spelers = new ArrayList<Speler>();
		for (int i = 0; i < (int) (spinner_playernumber.getValue()); i++) {
			spelers.add(new DummySpeler("Dummy" + (i + 1)));
		}
		Spel s = new Spel(spelers);
		s.addObserver(this);
		new Thread(s).start();
	}

	private void requestGame() {
		client.requestGame((int) spinner_multiplayers.getValue());
	}

	private void sendChatMessage() {
		client.sendChat(this.textField_chat.getText());
		this.textField_chat.setText("");
	}
	/**
	 * Proccest binnengekregen updates van het singleplayer spel of van de client
	 */
	@Override
	public void update(Observable arg0, Object arg1) {
		if (arg0 instanceof Spel) {
			((BordPanel) panel_Drawn).updateBord(((Spel) arg0).getBord());
			panel_Drawn.repaint();
			System.out.println("Updated Gui");
		} else if (arg0 instanceof Client) {
			if (arg1 != null && arg1 instanceof String) {
				addMessage((String) arg1);
			} else if (arg1 != null && arg1 instanceof Bord) {
				((BordPanel) panel_Drawn).updateBord((Bord) arg1);
				panel_Drawn.repaint();
				System.out.println("Updated Gui");
			}
		}

	}

	private void connectToServer() {
		if (client != null) {
			client.shutdown();
			client = null;
		}
		try {
			int port = Integer.parseInt(this.textField_Port.getText());
			client = new Client(textField_User.getText(),
					InetAddress.getByName(txtLocalhost.getText()), port);
			client.addObserver(this);
			new Thread(client).start();
		} catch (UnknownHostException e) {
			addMessage("Server not found");
		} catch (IOException e) {
			addMessage("Error connectiong to server...");
		}

		addMessage("Connecting to server...");
		if (this.chckbxEnableAi.isSelected()) {
			if (comboBox_AI.getSelectedIndex() >= 0
					&& comboBox_AI.getSelectedItem() != null) {
				if (client != null)
					client.setStrategie(ais.get(comboBox_AI.getSelectedItem()));
			}
		} else {
			if (client != null)
				client.setStrategie(new MensStrategie(ClientGUI.this));
		}

	}
	
	/**
	 * Zal een zet proberen te krijgen van de gebruiker via het BordPanel
	 * @param m De mensStrategie waarvoor de zet is.
	 */
	public void getSet(MensStrategie m) {
		((BordPanel) panel_Drawn).getSet(m);
	}

	/**
	 * Laat een bericht op de GUI en de standaard output zien
	 * @param s Het bericht om te tontn
	 */
	public void addMessage(String s) {
		System.out.println(s);
		this.textArea_msg.append(s + '\n');
	}

}
